package stream;

import java8.Employee;
import java8.Employee.*;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

//StreamAPI
public class TestStreamAPI3 {
	
	private List<Employee> emps = Arrays.asList(
			new Employee(102, "李四", 59, 6666.66, Employee.STATUS.BUBY),
			new Employee(101, "张三", 18, 9999.99,Employee.STATUS.FREE),
			new Employee(103, "王五", 28, 3333.33,Employee.STATUS.LEAVE),
			new Employee(104, "赵六", 8, 7777.77,Employee.STATUS.BUBY),
			new Employee(104, "赵六", 8, 7777.77,Employee.STATUS.BUBY),
			new Employee(104, "赵六", 8, 7777.77,Employee.STATUS.FREE),
			new Employee(105, "田七", 38, 5555.55,Employee.STATUS.BUBY)
	);
	//终止操作
	@Test
	public void test01(){
		//是否所有人都是BUBY状态
		boolean allMatch = emps.stream().allMatch(e->e.getStatus().equals(Employee.STATUS.BUBY));
		System.out.println(allMatch);  //false
		//是否至少只有一个是BUBY状态
		boolean anyMatch = emps.stream().anyMatch(e->e.getStatus().equals(Employee.STATUS.BUBY));
		System.out.println(anyMatch); //true
		//是否所有元素都不是BUBY状态
		boolean noneMatch = emps.stream().noneMatch(e->e.getStatus().equals(STATUS.BUBY));
		System.out.println(noneMatch); //false
		
	}
	@Test
	public void test02(){
		//获取最低工资的员工
		Optional<Employee> findFirst = emps.stream().
				sorted((x,y)-> Double.compare(x.getSalary(),y.getSalary())).findFirst();
		System.out.println(findFirst.get());
		//获取状态是FREE的任意一个员工
		Optional<Employee> findAny = emps.stream().
				filter(x->x.getStatus().equals(STATUS.FREE)).findAny();
		System.out.println(findAny.get());
		//获取最高的工资
		Optional<Double> max = emps.stream().map(x->x.getSalary()).max(Double::compareTo);
		System.out.println(max.get());
		//获取工资最低的人
		Optional<Employee> min = emps.stream().
				min((x,y)-> Double.compare(x.getSalary(), x.getSalary()));
		System.out.println(min.get());
		//获取忙碌的员工总数
		long count = emps.stream().filter(x->x.getStatus().equals(STATUS.BUBY)).count();
		System.out.println(count);
		
	}
	
	@Test
	public void test03(){
		//计算List中元素的和
		List<Integer> asList = Arrays.asList(1,2,3,4,5,6,7,8);
		//参数:  初始值(可无,能避免空指针), 运算  
		Integer reduce = asList.stream().reduce(0, (x, y)->x+y);
		//不断的从list中取元素赋值y与x运算,结果赋给x
		System.out.println(reduce);// 36
		//计算员工的工资总和
		Optional<Double> reduce2 = emps.stream().map(x->x.getSalary()).reduce(Double::sum);
		System.out.println(Math.ceil(reduce2.get())); //48889.0
	}

	@Test
	public void test04(){
		//搜索员工名字中六的出现次数
		Optional<Integer> reduce = emps.stream().map(Employee::getName)
		.flatMap(TestStreamAPI2::filterCharacter)  //转换成单个字符
		.map(x->{    //将对应字符转换为数字,六是1,其他是0
			if(x.equals('六')){//必须是单引号 ''
				return 1;
			}else{
				return 0;
			}
		}).reduce(Integer::sum);//求和计算次数
		System.out.println(reduce.get()); //3
	}
	@Test
	public void test05(){
		//将员工姓名转化为一个list,   
		//collect接受一个Collector接口实现,Collectors类有许多静态方法可以直接用
		List<String> collect = emps.stream()
				.map(Employee::getName).collect(Collectors.toList());
		System.out.println(collect);//[李四, 张三, 王五, 赵六, 赵六, 赵六, 田七]
		//将员工年龄转化为set         ,也可以直接   Collectors.toSet()            
		//collector的实现接口(需要一个供给型函数式接口的实现:返回转换的数据类型)
		HashSet<Integer> collect2 = emps.stream().map(Employee::getAge)
				.collect(Collectors.toCollection(HashSet::new));
		System.out.println(collect2);//[18, 38, 8, 59, 28]
		
		//求出最大工资                               //接受 比较接口实现类
		Optional<Double> collect3 = emps.stream().map(Employee::getSalary)
				.collect(Collectors.maxBy((x, y)-> Double.compare(x, y)));
		System.out.println(collect3.get());
		//	求出最小哦工资
		Optional<Double> collect4 = emps.stream().map(Employee::getSalary)
				.collect(Collectors.minBy(Double::compareTo));
		System.out.println(collect4.get());
		//求出所有人的工资和
		Double collect5 = emps.stream().collect(Collectors.summingDouble(Employee::getSalary));
		System.out.println(collect5);
		//求出平均工资
		Double collect6 = emps.stream().collect(Collectors.averagingDouble(Employee::getSalary));
		System.out.println(collect6);
		//求出20岁以上的员工总数
		Long collect7 = emps.stream().filter(x->x.getAge()>=20).collect(Collectors.counting());
		System.out.println(collect7);
		/**
		 * 还可以求出一个封装了平均值总数最大最小值的对象(分别有int,long,double三个数字类型的),根据这个对象获取其他值
		 */
		DoubleSummaryStatistics collect8 = emps.stream()
				.collect(Collectors.summarizingDouble(Employee::getSalary));
		collect8.getAverage();
		collect8.getCount();
		collect8.getMax();
		collect8.getMin();
		collect8.getSum();
	}
	
	@Test
	public void test06(){
		//按状态将员工分组,结果是Map
		Map<STATUS, List<Employee>> collect = emps.stream()
				.collect(Collectors.groupingBy(Employee::getStatus));
		System.out.println(collect);
		/**
		 * {FREE=[Employee [workCode=101, name=张三, age=18, salary=9999.99], 
		 * 		  Employee [workCode=104, name=赵六, age=8, salary=7777.77]], 
		 * LEAVE=[Employee [workCode=103, name=王五, age=28, salary=3333.33]], 
		 * BUBY=[Employee [workCode=102, name=李四, age=59, salary=6666.66], 
		 * 		Employee [workCode=104, name=赵六, age=8, salary=7777.77], 
		 * 		Employee [workCode=104, name=赵六, age=8, salary=7777.77], 
		 * 		Employee [workCode=105, name=田七, age=38, salary=5555.55]]}
		 */
		//按状态分组之后再分别按年龄分组
		Map<Employee.STATUS, Map<String, List<Employee>>> collect2 = emps.stream()                //( 先分组依据,再分组依据)
					.collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy(x->{
						if(x.getAge()>=65){
							return "老年人";
						}else if(x.getAge()>=30){
							return "中年人";
						}else{
							return "青年";
						}
		})));
	}
	@Test
	public void test07(){
		//进行reducing计算,工资求和1
		Optional<Double> sum = emps.stream()
				.map(Employee::getSalary)
				.collect(Collectors.reducing(Double::sum));
		System.out.println(sum.get());
		//用map-reduce计算出流中有多少个员工
		Optional<Integer> reduce = emps.stream().map((x)->1).reduce(Integer::sum);
		System.out.println(reduce.get());  //7
	}
}
